home *** CD-ROM | disk | FTP | other *** search
/ Dr. Windows 3 / dr win3.zip / dr win3 / PROGRAMR / OLE2BOOK.ZIP / CHAP12.ZIP / PATRON / PAGE.CPP < prev    next >
C/C++ Source or Header  |  1993-06-27  |  29KB  |  1,174 lines

  1. /*
  2.  * PAGE.CPP
  3.  * Modifications for Chapter 12
  4.  *
  5.  * Implementation of parts of the CPage class; those member functions
  6.  * dealing with mouse events are in PAGEMOUS.CPP
  7.  *
  8.  * Copyright (c)1993 Microsoft Corporation, All Rights Reserved
  9.  *
  10.  * Kraig Brockschmidt, Software Design Engineer
  11.  * Microsoft Systems Developer Relations
  12.  *
  13.  * Internet  :  kraigb@microsoft.com
  14.  * Compuserve:  >INTERNET:kraigb@microsoft.com
  15.  */
  16.  
  17.  
  18. #include "patron.h"
  19.  
  20.  
  21. /*
  22.  * CPage::CPage
  23.  * CPage::~CPage
  24.  *
  25.  * Constructor Parameters:
  26.  *  dwID            DWORD identifier for this page.
  27.  *  hWnd            HWND of the pages window (for repaints, etc).
  28.  *  pPG             LPCPages to the Pages window.
  29.  */
  30.  
  31. CPage::CPage(DWORD dwID, HWND hWnd, LPCPages pPG)
  32.     {
  33.     m_dwID     =dwID;
  34.     m_pIStorage=NULL;
  35.  
  36.     m_cOpens=0;
  37.     m_hWnd=hWnd;
  38.     m_pPG=pPG;
  39.  
  40.     m_dwIDNext      =0;
  41.     m_cTenants      =0;
  42.     m_hWndTenantList=NULL;
  43.     m_iTenantCur    =0xFFFF;    //Tenants are zero indexed.
  44.     m_pTenantCur    =NULL;
  45.  
  46.     m_uHTCode=HTNOWHERE;
  47.     m_uSizingFlags=0;
  48.     m_fTracking=FALSE;
  49.     m_hDC=NULL;
  50.  
  51.     return;
  52.     }
  53.  
  54.  
  55. CPage::~CPage(void)
  56.     {
  57.     m_hWnd=NULL;
  58.     Close(FALSE);
  59.     return;
  60.     }
  61.  
  62.  
  63.  
  64.  
  65.  
  66. /*
  67.  * CPage::GetID
  68.  *
  69.  * Return Value:
  70.  *  DWORD           dwID field in this page.  This function is only here
  71.  *                  to avoid hiding inline implementations in pages.h
  72.  */
  73.  
  74. DWORD CPage::GetID(void)
  75.     {
  76.     return m_dwID;
  77.     }
  78.  
  79.  
  80.  
  81.  
  82.  
  83.  
  84. /*
  85.  * CPage::FOpen
  86.  *
  87.  * Purpose:
  88.  *  Retrieves the IStorage associated with this page.  The IStorage is
  89.  *  owned by the page and thus the page always holds a reference count.
  90.  *  The caller should call ::Close or delete this page to match this open.
  91.  *
  92.  *  This function may be called multiple times resulting in additional
  93.  *  reference counts on the storage each of which must be matched with
  94.  *  a call to ::Close.  The last ::Close can be done through delete.
  95.  *
  96.  * Parameters:
  97.  *  pIStorage       LPSTORAGE in which this page lives.
  98.  *
  99.  * Return Value:
  100.  *  BOOL            TRUE if opening succeeds, FALSE otherwise.
  101.  */
  102.  
  103. BOOL CPage::FOpen(LPSTORAGE pIStorage)
  104.     {
  105.     HRESULT                 hr=NOERROR;
  106.     LPSTREAM                pIStream;
  107.     DWORD                   dwMode;
  108.     char                    szTemp[32];
  109.     BOOL                    fNew;
  110.     BOOL                    fCreated=FALSE;
  111.     TENANTLIST              tl;
  112.     LPTENANTINFO            pti;
  113.     ULONG                   cb;
  114.     LPMALLOC                pIMalloc;
  115.     UINT                    i;
  116.     LPTENANT                pTenant;
  117.     //CHAPTER12MOD
  118.     UINT                    cLinks;
  119.     LPOLELINK               pIOleLink;
  120.     LPUNKNOWN               pIUnknown;
  121.     UINT                    uRet;
  122.     OLEUIEDITLINKS          el;
  123.     LPCIOleUILinkContainer  pIUILinks;
  124.     HWND                    hWndDoc;
  125.     //End CHAPTER12MOD
  126.  
  127.     fNew=(NULL==m_pIStorage);
  128.  
  129.     if (!fNew)
  130.         {
  131.         m_cOpens++;
  132.         m_pIStorage->AddRef();
  133.         return TRUE;
  134.         }
  135.  
  136.     if (NULL==pIStorage)
  137.         return FALSE;
  138.  
  139.     /*
  140.      * Attempt to open the storage under this ID.  If there is none, then
  141.      * create it.  In either case we end up with an IStorage that we
  142.      * either save in pPage or release.
  143.      */
  144.  
  145.     GetStorageName(szTemp);
  146.     dwMode=STGM_TRANSACTED | STGM_READWRITE | STGM_SHARE_EXCLUSIVE;
  147.  
  148.     hr=pIStorage->OpenStorage(szTemp, NULL, dwMode, NULL, 0, &m_pIStorage);
  149.  
  150.     if (FAILED(hr))
  151.         {
  152.         hr=pIStorage->CreateStorage(szTemp, dwMode, 0, 0, &m_pIStorage);
  153.         fCreated=TRUE;
  154.         }
  155.  
  156.     if (FAILED(hr))
  157.         return FALSE;
  158.  
  159.     m_cOpens++;
  160.  
  161.     if (NULL==m_hWndTenantList)
  162.         {
  163.         /*
  164.          * The first time we open this page, create the hidden listbox
  165.          * we'll use to track tenants.  We give it the owner-draw style
  166.          * so we can just store pointers in it.
  167.          */
  168.         m_hWndTenantList=CreateWindow("listbox", "Tenant List"
  169.             , WS_POPUP | LBS_OWNERDRAWFIXED, 0, 0, 100, 100
  170.             , HWND_DESKTOP, NULL, m_pPG->m_hInst, NULL);
  171.  
  172.         if (NULL==m_hWndTenantList)
  173.             return FALSE;
  174.         }
  175.  
  176.     //If this is brand-new, we're done.
  177.     if (fCreated)
  178.         return TRUE;
  179.  
  180.  
  181.     /*
  182.      * Now open the stream we saved in ::Close and load all the
  183.      * tenants listed in there.  If there are none, then we don't
  184.      * have to load squat.
  185.      */
  186.  
  187.     hr=m_pIStorage->OpenStream(SZSTREAMTENANTLIST, NULL, STGM_DIRECT
  188.         | STGM_READ | STGM_SHARE_EXCLUSIVE, 0, &pIStream);
  189.  
  190.     if (FAILED(hr))
  191.         return FALSE;
  192.  
  193.     if (SUCCEEDED(CoGetMalloc(MEMCTX_SHARED, &pIMalloc)))
  194.         {
  195.         pIStream->Read((LPVOID)&tl, sizeof(tl), NULL);
  196.         m_cTenants=tl.cTenants;
  197.         m_dwIDNext=tl.dwIDNext;
  198.         m_iTenantCur=0;
  199.  
  200.         cb=tl.cTenants*sizeof(TENANTINFO);
  201.  
  202.         if (0!=cb)
  203.             {
  204.             pti=(LPTENANTINFO)pIMalloc->Alloc(cb);
  205.  
  206.             if (NULL!=pti)
  207.                 {
  208.                 pIStream->Read((LPVOID)pti, cb, NULL);
  209.  
  210.                 for (i=0; i < m_cTenants; i++)
  211.                     {
  212.                     if (FTenantAdd(-1, (pti+i)->dwID, &pTenant))
  213.                         {
  214.                         pTenant->FLoad(m_pIStorage, &(pti+i)->fe, &(pti+i)->rcl);
  215.  
  216.                         //CHAPTER12MOD
  217.                         //Make sure it knows about the show state.
  218.                         pTenant->ShowObjectType(m_pPG->m_fShowTypes);
  219.                         //End CHAPTER12MOD
  220.                         }
  221.                     }
  222.  
  223.                 pIMalloc->Free((LPVOID)pti);
  224.                 }
  225.             }
  226.  
  227.         pIMalloc->Release();
  228.         }
  229.  
  230.     pIStream->Release();
  231.  
  232.     //Get and select the first tenant
  233.     if (FTenantGet(0, &m_pTenantCur, FALSE))
  234.         m_pTenantCur->Select(TRUE);
  235.  
  236.  
  237.     //CHAPTER12MOD
  238.     /*
  239.      * Update all the links in this page, showing the progress indicator
  240.      * as it's happening.  We use the same IOlUILinkContainer
  241.      * implementation as we do for the links dialog, passing it to
  242.      * OleUIUpdateLinks which does everything for us.
  243.      *
  244.      * We might also optimize this to not do anything if there are no
  245.      * automatic links, but it's not a big concern.
  246.      */
  247.  
  248.     //First, count the number of automatic links.
  249.     cLinks=0;
  250.  
  251.     for (i=0; i < m_cTenants; i++)
  252.         {
  253.         if (FTenantGet(i, &pTenant, FALSE))
  254.             {
  255.             DWORD       dw;
  256.  
  257.             pTenant->ObjectGet(&pIUnknown);
  258.             hr=pIUnknown->QueryInterface(IID_IOleLink, (LPLPVOID)&pIOleLink);
  259.             pIUnknown->Release();
  260.  
  261.             if (FAILED(hr))
  262.                 continue;
  263.  
  264.             pIOleLink->GetUpdateOptions(&dw);
  265.             pIOleLink->Release();
  266.  
  267.             if (OLEUPDATE_ALWAYS==dw)
  268.                 cLinks++;
  269.             }
  270.         }
  271.  
  272.     //If we have any automatic links, invoke the update dialog.
  273.     if (0==cLinks)
  274.         return TRUE;
  275.  
  276.     //Create an IOleUILinkContainer instantiation.
  277.     if (!m_pPG->FGetUILinkContainer(&pIUILinks))
  278.         return TRUE;    //Guess we can't update, oh well.
  279.  
  280.     hWndDoc=GetParent(m_hWnd);
  281.     LoadString(m_pPG->m_hInst, IDS_CAPTION, szTemp, sizeof(szTemp));
  282.  
  283.     if (!OleUIUpdateLinks(pIUILinks, hWndDoc, szTemp, cLinks))
  284.         {
  285.         /*
  286.          * If updating failed, ask to show the links dialog.  NOTE:
  287.          * OleUIPromptUser has a variable wsprintf type argument list
  288.          * after the hWnd parameter!  Use appropriate typecasting!
  289.          */
  290.         uRet=OleUIPromptUser(IDD_CANNOTUPDATELINK, hWndDoc, (LPSTR)szTemp);
  291.  
  292.         if (ID_PU_LINKS==uRet)
  293.             {
  294.             //Throw up the links dialog.
  295.             _fmemset(&el, 0, sizeof(el));
  296.             el.cbStruct=sizeof(el);
  297.             el.hWndOwner=hWndDoc;
  298.             el.lpOleUILinkContainer=(LPOLEUILINKCONTAINER)pIUILinks;
  299.             OleUIEditLinks((LPOLEUIEDITLINKS)&el);
  300.             }
  301.         }
  302.  
  303.     m_pPG->m_fDirty=pIUILinks->m_fDirty;
  304.     pIUILi